import uuid
from datetime import datetime, timedelta
import jwt
from flask import current_app, request, jsonify
from functools import wraps
from app.models.database import db
from app.models.user import User, UserPreference
from app.utils.logger import logger

class AuthService:
    """认证服务类"""
    
    @staticmethod
    def generate_token(user_id, role):
        """生成JWT令牌"""
        payload = {
            'user_id': user_id,
            'role': role,
            'exp': datetime.utcnow() + timedelta(days=1),  # 令牌有效期1天
            'iat': datetime.utcnow()
        }
        
        # 使用应用密钥签名令牌
        token = jwt.encode(payload, current_app.config.get('SECRET_KEY', 'your-secret-key'), algorithm='HS256')
        return token
    
    @staticmethod
    def decode_token(token):
        """解码JWT令牌"""
        try:
            payload = jwt.decode(token, current_app.config.get('SECRET_KEY', 'your-secret-key'), algorithms=['HS256'])
            return payload
        except jwt.ExpiredSignatureError:
            logger.warning("Token已过期")
            return None
        except jwt.InvalidTokenError:
            logger.warning("无效的Token")
            return None
    
    @staticmethod
    def register_user(username, email, password, role='user', organization=None, department=None):
        """注册新用户"""
        # 检查用户名是否已存在
        if User.query.filter_by(username=username).first():
            logger.warning(f"用户名 {username} 已存在")
            return {'success': False, 'message': '用户名已存在'}
        
        # 检查邮箱是否已存在
        if User.query.filter_by(email=email).first():
            logger.warning(f"邮箱 {email} 已存在")
            return {'success': False, 'message': '邮箱已存在'}
        
        # 创建新用户
        user = User(
            username=username,
            email=email,
            role=role,
            organization=organization,
            department=department
        )
        user.set_password(password)
        
        try:
            db.session.add(user)
            db.session.commit()
            
            # 创建用户首选项
            preference = UserPreference(user_id=user.id)
            db.session.add(preference)
            db.session.commit()
            
            logger.info(f"新用户注册成功: {username}")
            return {'success': True, 'user_id': user.id}
        except Exception as e:
            db.session.rollback()
            logger.error(f"用户注册失败: {str(e)}")
            return {'success': False, 'message': '注册失败，请稍后重试'}
    
    @staticmethod
    def login_user(username, password):
        """用户登录"""
        # 查找用户
        user = User.query.filter_by(username=username).first()
        
        if not user or not user.check_password(password):
            logger.warning(f"登录失败: 用户名 {username}")
            return {'success': False, 'message': '用户名或密码错误'}
        
        if not user.is_active:
            logger.warning(f"用户已禁用: {username}")
            return {'success': False, 'message': '用户已被禁用'}
        
        # 更新最后登录时间
        user.last_login_at = datetime.utcnow()
        db.session.commit()
        
        # 生成令牌
        token = AuthService.generate_token(user.id, user.role)
        
        logger.info(f"用户登录成功: {username}")
        return {
            'success': True,
            'token': token,
            'user': user.to_dict()
        }
    
    @staticmethod
    def update_user_profile(user_id, **kwargs):
        """更新用户资料"""
        user = User.query.get(user_id)
        if not user:
            return {'success': False, 'message': '用户不存在'}
        
        # 更新用户信息
        for key, value in kwargs.items():
            if hasattr(user, key) and key not in ['id', 'password_hash', 'created_at']:
                setattr(user, key, value)
        
        try:
            db.session.commit()
            logger.info(f"用户资料更新成功: {user.username}")
            return {'success': True, 'user': user.to_dict()}
        except Exception as e:
            db.session.rollback()
            logger.error(f"用户资料更新失败: {str(e)}")
            return {'success': False, 'message': '更新失败'}
    
    @staticmethod
    def update_user_password(user_id, old_password, new_password):
        """更新用户密码"""
        user = User.query.get(user_id)
        if not user:
            return {'success': False, 'message': '用户不存在'}
        
        # 验证旧密码
        if not user.check_password(old_password):
            return {'success': False, 'message': '旧密码错误'}
        
        # 设置新密码
        user.set_password(new_password)
        
        try:
            db.session.commit()
            logger.info(f"用户密码更新成功: {user.username}")
            return {'success': True}
        except Exception as e:
            db.session.rollback()
            logger.error(f"用户密码更新失败: {str(e)}")
            return {'success': False, 'message': '密码更新失败'}

# 装饰器：验证用户是否已认证
def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = None
        
        # 从请求头获取令牌
        if 'Authorization' in request.headers:
            auth_header = request.headers['Authorization']
            if auth_header.startswith('Bearer '):
                token = auth_header.split(' ')[1]
        
        if not token:
            return jsonify({'error': '缺少认证令牌'}), 401
        
        # 解码令牌
        payload = AuthService.decode_token(token)
        if not payload:
            return jsonify({'error': '无效或已过期的令牌'}), 401
        
        # 获取用户ID和角色
        user_id = payload['user_id']
        user_role = payload['role']
        
        # 查找用户
        user = User.query.get(user_id)
        if not user:
            return jsonify({'error': '用户不存在'}), 401
        
        if not user.is_active:
            return jsonify({'error': '用户已被禁用'}), 403
        
        # 将用户信息注入到请求上下文
        request.current_user = user
        request.current_user_role = user_role
        
        return f(*args, **kwargs)
    return decorated

# 装饰器：验证用户角色
def role_required(required_role):
    def decorator(f):
        @wraps(f)
        @token_required
        def decorated(*args, **kwargs):
            current_role = request.current_user_role
            
            # 角色权限层级：admin > user > guest
            role_levels = {'admin': 3, 'user': 2, 'guest': 1}
            
            if role_levels.get(current_role, 0) < role_levels.get(required_role, 0):
                return jsonify({'error': '权限不足'}), 403
            
            return f(*args, **kwargs)
        return decorated
    return decorator